package ads.server;

import javax.swing.JOptionPane;

import org.apache.log4j.Logger;
import org.omg.CORBA.Request;

import ads.exception.SpreadRemoteException;
import ads.util.GameInfo;
import ads.util.PlayerInfo;

import spread.AdvancedMessageListener;
import spread.MembershipInfo;
import spread.SpreadException;
import spread.SpreadGroup;
import spread.SpreadMessage;

public class ServerAdvanceMessageListener implements AdvancedMessageListener {
	private ServerImpl server;
	private static final Logger log = Logger
			.getLogger(ServerAdvanceMessageListener.class.getName());

	public ServerAdvanceMessageListener(SpreadMember serverImpl) {
		super();
		server = (ServerImpl) serverImpl;

	}

	@Override
	public void membershipMessageReceived(SpreadMessage message) {
		log.debug("a membershipMessage was Received:" + message);
		MembershipInfo info = message.getMembershipInfo();
		SpreadGroup[] members = info.getMembers();
		if (members.length > 0) {
			if (info.isCausedByJoin()) {
				log.info("new server " + info.getJoined() + " was joind  ");
				server.handleMemberJoined(info.getJoined());
			} else if (info.isCausedByLeave()) {
				log.info("server " + info.getLeft() + " was left");
				SpreadGroup downServer = info.getLeft();
				server.handleMemberLeftOrDisconnected(downServer, members);
			} else if (info.isCausedByDisconnect()) {
				log.info("server " + info.getDisconnected()
						+ " was discnnected");
				SpreadGroup downServer = info.getLeft();
				server.handleMemberLeftOrDisconnected(downServer, members);
			} else if (info.isCausedByNetwork()) {
				log.debug("NETWORK change");
				JOptionPane.showMessageDialog(server.gui,
						"notwort was changed,network was partitioned");
			}
			try {
				server.requestor.updateServers(server.primaryServerName);
			} catch (SpreadRemoteException e) {
				log.error(e);
				e.printStackTrace();
			}
			DisplayMessage(message);
		}
	}

	@Override
	public void regularMessageReceived(SpreadMessage message) {
		log.debug("a regularMessage was Received:" + message);
		// DisplayMessage(message);
		Object obj;
		try {
			obj = message.getObject();
			if (obj == null) {
				return;
			} else {
				if (obj instanceof UpdateMessageData) {
					UpdateMessageData msgData = (UpdateMessageData) obj;
					if (msgData.getObject() instanceof PlayerInfo) {
						PlayerInfo pi = (PlayerInfo) msgData.getObject();
						UpdateOperator op = msgData.getOperator();
						log.debug("update message:" + op + " " + pi);
						server.updatePlayerInfo(op,pi);
					} else if (msgData.getObject() instanceof GameInfo) {
						GameInfo gi = (GameInfo) msgData.getObject();
						UpdateOperator op = msgData.getOperator();
						log.debug("update message:" + op + " " + gi);
						server.updateGameInfo(op,gi);
					}
				} else if (obj instanceof SpreadRequestMessage) {
					SpreadRequestMessage rm = (SpreadRequestMessage) obj;
					new SpreadInvokerThread(server, rm).start();
				} else if (obj instanceof SpreadResponseMessage) {
					SpreadMessageQueque.putMsg((SpreadResponseMessage) obj);
				}
			}
		} catch (SpreadException e) {
			log.error(e);

		}

	}

	public static void DisplayMessage(SpreadMessage msg) {
		try {
			System.out.println("*****************RECTHREAD Received Message "
					+ msg + "************");
			if (msg.isRegular()) {
				System.out.print("Received a ");
				if (msg.isUnreliable())
					System.out.print("UNRELIABLE");
				else if (msg.isReliable())
					System.out.print("RELIABLE");
				else if (msg.isFifo())
					System.out.print("FIFO");
				else if (msg.isCausal())
					System.out.print("CAUSAL");
				else if (msg.isAgreed())
					System.out.print("AGREED");
				else if (msg.isSafe())
					System.out.print("SAFE");
				System.out.println(" message.");

				System.out.println("Sent by  " + msg.getSender() + ".");

				System.out.println("Type is " + msg.getType() + ".");

				if (msg.getEndianMismatch() == true)
					System.out.println("There is an endian mismatch.");
				else
					System.out.println("There is no endian mismatch.");

				SpreadGroup groups[] = msg.getGroups();
				System.out.println("To " + groups.length + " groups.");

				byte data[] = msg.getData();
				System.out.println("The data is " + data.length + " bytes.");

				System.out.println("The message is: " + new String(data));
			} else if (msg.isMembership()) {
				MembershipInfo info = msg.getMembershipInfo();
				printMembershipInfo(info);
			} else if (msg.isReject()) {
				// Received a Reject message
				System.out.print("Received a ");
				if (msg.isUnreliable())
					System.out.print("UNRELIABLE");
				else if (msg.isReliable())
					System.out.print("RELIABLE");
				else if (msg.isFifo())
					System.out.print("FIFO");
				else if (msg.isCausal())
					System.out.print("CAUSAL");
				else if (msg.isAgreed())
					System.out.print("AGREED");
				else if (msg.isSafe())
					System.out.print("SAFE");
				System.out.println(" REJECTED message.");

				System.out.println("Sent by  " + msg.getSender() + ".");

				System.out.println("Type is " + msg.getType() + ".");

				if (msg.getEndianMismatch() == true)
					System.out.println("There is an endian mismatch.");
				else
					System.out.println("There is no endian mismatch.");

				SpreadGroup groups[] = msg.getGroups();
				System.out.println("To " + groups.length + " groups.");

				byte data[] = msg.getData();
				System.out.println("The data is " + data.length + " bytes.");

				System.out.println("The message is: " + new String(data));
			} else {
				System.out.println("Message is of unknown type: "
						+ msg.getServiceType());
			}
		} catch (Exception e) {
			log.error(e);
		} finally {
			System.out.println("*************EDN RECTHREAD Received Message "
					+ msg + "************");
		}
	}

	public static void printMembershipInfo(MembershipInfo info) {
		SpreadGroup group = info.getGroup();
		if (info.isRegularMembership()) {
			SpreadGroup members[] = info.getMembers();
			MembershipInfo.VirtualSynchronySet virtual_synchrony_sets[] = info
					.getVirtualSynchronySets();
			MembershipInfo.VirtualSynchronySet my_virtual_synchrony_set = info
					.getMyVirtualSynchronySet();

			System.out.println("REGULAR membership for group " + group
					+ " with " + members.length + " members:");
			for (int i = 0; i < members.length; ++i) {
				System.out.println("\t\t" + members[i]);
			}
			System.out.println("Group ID is " + info.getGroupID());

			System.out.print("\tDue to ");
			if (info.isCausedByJoin()) {
				System.out.println("the JOIN of " + info.getJoined());
			} else if (info.isCausedByLeave()) {
				System.out.println("the LEAVE of " + info.getLeft());
			} else if (info.isCausedByDisconnect()) {
				System.out.println("the DISCONNECT of "
						+ info.getDisconnected());
			} else if (info.isCausedByNetwork()) {
				System.out.println("NETWORK change");
				for (int i = 0; i < virtual_synchrony_sets.length; ++i) {
					MembershipInfo.VirtualSynchronySet set = virtual_synchrony_sets[i];
					SpreadGroup setMembers[] = set.getMembers();
					System.out.print("\t\t");
					if (set == my_virtual_synchrony_set) {
						System.out.print("(LOCAL) ");
					} else {
						System.out.print("(OTHER) ");
					}
					System.out.println("Virtual Synchrony Set " + i + " has "
							+ set.getSize() + " members:");
					for (int j = 0; j < set.getSize(); ++j) {
						System.out.println("\t\t\t" + setMembers[j]);
					}
				}
			}
		} else if (info.isTransition()) {
			System.out.println("TRANSITIONAL membership for group " + group);
		} else if (info.isSelfLeave()) {
			System.out.println("SELF-LEAVE message for group " + group);
		}
	}

}
